-- DDL数据定义语言
-- DML数据操作语言
-- DCL数据控制语言
-- DQL数据查询语言

-- all,all privleges(所有权限)
-- select(查询数据)
-- insert(插入数据)
-- update(修改数据)
-- dalete(删除数据)
-- alter(修改表)
-- drop(删除数据库/表/视图)
-- create(创建数据库/表/视图)


-- select from 表名1 表别名，表名2 表别名;给表名起别名


# DDL语句	
/*
select databases();查询当前数据库
show databases;查询所有数据库
create database [if not exists] 数据库名 [default charset 字符集] [collate 排序规则];创建数据库
drop database [if exists ] 数据库名;删除数据库
use 数据库名;使用数据库


DDL-表操作-查询（前提是进入的当前数据库）
show tables;查询当前数据库所有表
desc 表名;查询表结构
show create table 表名;查询指定表的建表语句


DDL-表操作-创建
create table 表名(
	字段1 字段1类型[comment 字段1注释],
    字段2 字段2类型[comment 字段2注释],
    字段3 字段3类型[comment 字段3注释],
    ....
    字段n 字段n类型[comment 字段n注释]
)[comment 表注释];


DDL-表操作-修改
alter table 表名 add 字段名 类型(长度) [comment 注释] [约束];  --添加字段
alter table 表名 字段名 新数据类型(长度); -- 修改数据类型
alter table 表名 change 旧字段名 新字段名 类型(长度) [comment 注释] [约束]; --修改字段名和字段类型
drop table [if exists]表名; 删除表
truncate table 表名; --删除指定表，并重新创建该表
alter table 表名 drop 字段名; --删除字段
alter table 表名 rename to 新表名; --修改表名


DDL-表操作-数据类型-数值类型

	  大小|有符号范围signed|无符号范围unsigned|描述|
tinyint(1)(-128， 127)(0, 255)(小整数值)
smallnt(2)(-32768, 32767)(0, 65535)(大整数值)
medtumtnt(3)(-8388608, 8388607)(0, 16777215)(大整数值)
int或integer(4)(-2147483648，2147483647)(0， 4294967295)(大整数值)
btgint(8)(-2^63, 2^63-1)()(极大整数值)
float(4)(单精度浮点数值)
double(8)(双精度浮点数值)
dbctmal(?)(依赖于m（精度）和D（标度）的值)(依赖于m（精度）和D（标度)(小数值（精确定点数）)
精度是数的位数，标度是数的小数位


-字符串类型
char()(定长字符串)
varchar()(变长字符串)
二进制
tinyblob()(不超过255个字符的二进制数据)
tinyext()(短文本字符串)
blob()(二进制形式的长文本数据)
text()(长文本数据)
mediumblob()(二进制形式的中等长度文本数据)
mediumtext()(中等长度文本数据)
longblob()(二进制形式的中等长度文本数据)
longtext()(极大文本数据)


日期类型
date(3)(yyyy-mm-dd)(日期值)
time(3)(hh:mm:ss)(时间值或持续时间)
year(1)(yyyy)(年份值)
datetime(8)(yyyy-mm-dd hh:mm:ss)(混合日期和时间值)
timestamp(4)(yyyy-mm-dd hh:mm:ss)(混合日期和时间值，时间戳)

DDL小结
1.添加数据,一一对应
insert into 表名(字段1, 字段2...)values(值1, 值2...)[,(值1, 值2...)];
2.修改数据,注意条件不然修改整张表的数据
update 表名 set 字段1 = 值1, 字段2 = 值2 [where 条件];
3.删除数据，注意条件不然删除整张表的数据
delete from 表名 [where 条件];
*/


-- DCL用来管理数据库用户，控制数据库访问权限
/*
DCL-用户管理
查询用户
use mysql;
select * from user;在MySQL中用户信息储存在mysql数据库中的user表中

创建用户
create user '用户名'@'主机名' identified by '密码';

修改用户密码
alter user '用户名'@'主机名' identfied with mysql_native_password(加密方式) by '新密码';

删除用户
drop user '用户名'@'主机名';

DCL-权限控制
all,all privleges(所有权限)
select(查询数据)
insert(插入数据)
update(修改数据)
dalete(删除数据)
alter(修改表)
drop(删除数据库/表/视图)
create(创建数据库/表/视图)

查询权限
show grants for '用户名'@'主机名';
授予权限
grant 权限列表 on 数据库名.表名 to '用户名'@'主机名';
撤销权限
revoke 权限列表 on 数据库名.表名 from '用户名'@'主机名';
注意多个权限之间，使用都好分隔 
授权时，数据库名和表名可以使用*进行通配，代表所有 
例如：grant all on *.* to 'zhangsan'@'localhost';(所有数据库的所有表的权限，类似超级管理员)
*/


-- 函数
/*
字符串函数
数值函数
日期函数
流程函数

函数--字符串函数
concat(s1, s2, .... sn)(将字符串拼接)
lower(str)(将字符串str全部转为小写)
upper(str)(将字符串str全部转为大写)
lpad(str, n, pad)(左填充，用字符串pad对str的左边进行填充，达到n个字符串长度)
rpad(str, n, pad)(与上一个函数一样，不过是右填充)
trim(str)(去掉字符串头部和尾部的空格)
substring(str, start, len)(返回字符串str从start位置起的len个长度的字符串(注意索引由1开始)

函数--数值函数
ceil(x)(向上取整)
floor(x)(向下取整)
mod(x, y)(返回x/y的模)
rand()(返回0 - 1内地随机数)
round(x, y)(求参数x的四舍五入的值，保留y为小数)

函数-日期函数
curdate()(返回当前日期)
curtime()(返回当前时间)
now()(返回当前日期和时间)
year(date)(获取指定date的年份)
month(date)(获取指定date的月份)
day(date)(获取指定date的日期)
date_add(date, intervalexpr type)(返回一个日期/时间值加上一个时间间隔expr后的时间值)(type:day, month, year)
datediff(date1, date2)(返回起始时间date1和结束时间date2之间相差天数)(前减后)

函数-流程函数
if(value, t, f)(若value为true，则返回t，否则返回f)
ifnull(value1, value2)(若value1不为空，返回value1，否则返回value2)
case when [val1] then [res1]...else[default] end(若val1为true，返回res1，否则返回default默认值)
case[expr] when [val1] then [res1]...else[default] end(若expr的值等于val1，返回res1，否则返回default默认值)

*/

 
/*
约束-概述-约束演示-外键约束
概述：约束是作用于表中字段上的规则，用于限制存储在表中的数据
分类：
not null(唯一约束)(限制该字段的数据不能为null)
unique(唯一约束)(保证该字段的所有数据都是唯一，不重复的)
primary key(主键约束)(主键是一行数据的唯一标识，要求非空且唯一)
default(默认约束)(保存数据时，若未指定该字段的值，则采用默认值)
check(检查约束)(保证字段值满足某一个条件)

foreign key(外键约束)(用来让两张表的数据之间建立连接，保证数据的一致性和完整性)
外键约束：用来让两张表的数据之间建立链接，从而保证数据的一致性完整性
语法：
1.
create table 表名(
	字段名 数据类型
    ...
    [constraint] [外键名称] foreign key (外键字段名) references 主表(主表列名)
);
2.
alter table 表名 add constraint 外键名称 foreign key(外键字段名) references 主表(主表列名);
外键名称仅仅是名称，并无关键字
-------------------------------------------------------------------------例子
CREATE TABLE IF NOT EXISTS `student`(
	`id` INT(4) NOT NULL AUTO_INCREMENT COMMENT '学号',
	`name` VARCHAR(30) NOT NULL DEFAULT '匿名' COMMENT '姓名',
	`pwd` VARCHAR(20) NOT NULL DEFAULT '123456' COMMENT '密码',
	`sex` VARCHAR(2)	NOT NULL DEFAULT '女' COMMENT '性别',
	`birthday` DATETIME DEFAULT NULL COMMENT '出生日期',
	`address` VARCHAR(100) DEFAULT NULL COMMENT '家庭住址',
	`email` VARCHAR(50) DEFAULT NULL COMMENT '邮箱',
	`gradeid` INT(10) NOT NULL COMMENT '学生的年级',
	PRIMARY KEY (`id`),
	KEY `FK_gradeid` (`gradeid`),
	CONSTRAINT `FK_gradeid` FOREIGN KEY (`gradeid`) REFERENCES `grade`(`gradeid`)给student表中的gradeid添加外键约束，关联grade表中的gradeid字段
)ENGINE=INNODB DEFAULT CHARSET=utf8

-- 创建年级表
CREATE TABLE `grade`(
	`gradeid` INT(10) NOT NULL COMMENT '年级id',
	`gradename` VARCHAR(50) NOT NULL COMMENT '年纪名称',
	PRIMARY KEY (`gradeid`)
)ENGINE=INNODB DEFAULT CHARSET=utf8
---------------------------------------------------------------------------


3.删除外键
alter table 表名 drop foreign ley 外键名称;
---------------------------------------------------------------

4.外键约束-删除/更新行为
no action(当在父表中删除/更新对应记录时，首先检查该记录是否有对应外键，若有则不允许删除/更新)
restrict(与no action一致)
cascade(---，如果有，则也在删除/更新外键在子表中的记录)
set null(---，若有则设置子表中该外键值为null（这就要求外键允许取null）)
set dafault(父表有变更时，子表将外键列设置成一个默认值（innodb不支持）)
设置外键-删除/更新行为
alter table 表名 add constraint 外键名称 foreign key(外键字段名) references 主表(主表列名) on update cascade on delete cascade;因为外键关联两张表，所以需要设置两张表的删除/更新行为
在更换时将cascade更换为其他即可，注意两个cascade要一致
*/
----------------------------------------------------------------------------------










/*多表查询
指从多张表中查询数据
笛卡尔积：集合a与集合b的所有组合情况（在多表查询时，需要消除无效的笛卡尔积）
分类：
内连接：相当于查询a，b交际部分数据
外连接：
	左外连接：查询左表所有数据，以及两张表交集部分数据
	右外连接：查询右表所有数据，以及两张表交集部分数据
	全外连接：查询左右表所有数据，以及两张表交集部分数据
自连接：当前表自身的连接查询，自连接必须使用表别名
*/
-- select * from test_peole, test_dept where test_peole.dept_id = test_dept.id;这就是消除笛卡尔积的是示范
---------------------------------------------------------------------
/*内连接
语法：
隐式内连接
select 字段列表 from 表1，表2... where 条件...;
显式内连接
select 字段列表 from 表1 [inner] join 表2 on 连接条件;
*/ 
-------------------------------------------------------------
/*外连接
左外语法：
select 字段列表 from 表1 left [outer] join 表2 on 连接条件;
右外语法：
select 字段列表 from 表1 right [outer] join 表2 on 连接条件;
左右的位置是可以互换的
全外语法：
select 字段列表 from 表1 full [outer] join 表2 on 连接条件;
*/
---------------------------------------------------------------------
/*自连接
语法：
select 字段列表 from 表1 别名1 join 表1 别名2 on 条件;
自连接查询，可以说内连接查询，也可以是外连接查询
自连接可以用隐式，也可以用显式
*/
----------------------------------------------------------------------
/*联合查询-union，union all
对于union查询，就是把多次查询的结果合并起来，形成一个新的查询结果集
语法：
select 字段列表 from 表a...
union [all]
select 字段列表 from 表b...其实就是把表a和表b的查询结果合并起来
-------------------------------------------------------------
union all和union的区别：
union all会将所有的结果都查询出来，包括重复的
union会将重复的结果去除，只保留一条
注意：
1.要求查询的列数必须一致（字段列表一致）
2.要求查询的列的类型和顺序最好一致
3.union默认去重，union all不去重
4.可以使用小括号改变优先级
5.可以使用order by对结果集进行排序
*/
--------------------------------------------------------------

/*子查询
概念：SQL语句中嵌套select语句，称为嵌套查询，又称子查询
语法
select * form t1 where column1 = (select column1 from t2 );
子查询外部的语句可以是任何语句，不仅仅是select语句
子查询内部的查询结果被外部语句使用
分类：
1.标量子查询(结果集只有一行一列)
2.列子查询(结果集只有一列多行)
3.行子查询(结果集有一行多列)
4.表子查询(结果集一般为多行多列)
*/

-------------------------------------------------------------------
/*标量子查询
子查询返回的结果是单个值（数字，字符串，日期等），最简单的形式，这种子查询称为标量子查询
常用的操作符：= <> > >= < <=
例如
查询市场部的所有信息
select id from dept where name = '市场部';
select * from dept where name = (select name from dept where id = 1);
查询张无忌在入职日期之后的信息
select entrydate from emp where name = '张无忌';
select * from emp where entrydate > (select entrydate from emp where name = '张无忌');
*/
---------------------------------------------------------
/*列子查询
子查询返回的结果是一列（可以说多行）
常用的操作符：in not in any some all
in 在指定的集合范围之内，多选一
not in 不在指定的集合范围之内
any 子查询返回列表中，有任意一个满足即可
some 与any相同，使用some的地方都可以使用any
all 子查询返回列表的所有值都必须满足
例子
查询销售部与市场不的所有员工信息
select id from dept where name = '销售部' or name = '市场部';
select * from emp where deptid in (select id from dept where name = '销售部' or name = '市场部');
查询比财物部所有人工资都高的员工信息
select id from dept where name = '财务部';
select salary from emp where deptid = (select id from dept where name = '财务部');
select * from emp where salary > all (select salary from emp where deptid = (select id from dept where name = '财务部'));
*/
--------------------------------------------------------------------------------

/*行子查询
子查询返回的结果是一行（可以说多列）
常用的操作符：= <> in,  not in
例子
查询与张无忌的薪资即直属领导相同的员工信息
select salary, namagerid from enp where name = '张无忌';返回形式是一行
select * from emp (salary, namagerid) = (select salary, namagerid from enp where name = '张无忌');组合条件干好符合返回形式
*/
--------------------------------------------------------------
/*表子查询
子查询返回的结果是多行多列
常用的操作符：in
例子
查询与‘a'‘b'的职位和薪资相同的员工信息
select job, salary from emp where name = 'a' or name = 'b';此时是多行数据
select * from emp (job, salary) in (select job, salary from emp where name = 'a' or name = 'b');
查询入职时间是"2006-01-01"之后的员工信息，及其部门信息
select entrydate from emp where entrydate > '2006-01-01';
select * from (select * from emp where entrydate > '2006-01-01') e left join dept d on e.deptid = d.id;
*/
------------------------------------------------------------------------




--------------事务


/*简介
事务是一组操作的集合，他说一个不可分割的工作单位，事务会把所有的操作作为一个整体一起向系统提交或撤销操作请求，即这些操作要么同时成功，要么同时失败
在MySQL中的事务是自动提交的，也就是说，当执行一条DML语句时，MySQL会立即将结果进行提交
*/
-----------------------------------------------------
/*事务操作
查看/设置事务提交方式
select @@autocommit; 返回1是自动提交，返回0是手动提交
@表示局部变量，@@表示全局变量
set autocommit = 1; 设置自动提交
set autocommit = 0; 设置手动提交
提交事务
commit;
回滚事务
rollback;
以上是修改了事务提交的方式
当不修改事务提交时的事务操作有
开启事务
start transaction 或 begin;
提交事务
commit;
回滚事务
rollback;
*/
------------------------------------------------------
/*事务的四大特性
原子性：是不可分割的最小操作单位，要么同时成功，要么同时失败
一致性：事务完成时，必须使所有的数据都保持一致状态
隔离性：数据库系统提供的隔离机制，保证事务在不受外部并发操作影响的独立环境下运行
持久性：事务一旦提交或回滚，它对数据库中的数据的改变就是永久的
*/
---------------------------------------------------------
/*并发事务问题
脏读：一个事务读取到了另一个事务还没有提交的数据
不可重复读：在同一个事务中，多次读取表中的数据返回的结果不一致
幻读：一个事务操作（DML）数据表中所有记录，另一个事务添加了一条数据，则第一个事务查询不到自己的修改
*/
-----------------------------------------------------------
/*事务的隔离级别
read uncommitted(读取未提交内容)：最低的隔离级别，允许读取尚未提交的数据变更，可能会导致脏读、不可重复读和幻读
read committed(读取提交内容)：允许读取并发事务已经提交的数据，可以阻止脏读，但是幻读或不可重复读仍有可能发生
repeatable read(可重复读)(mysql默认隔离级别)：对同一字段的多次读取结果都是一致的，除非数据是被本身事务自己所修改，可以阻止脏读和不可重复读，但幻读仍有可能发生
serializable(串行化)：最高的隔离级别，完全服从ACID的隔离级别。所有的事务依次逐个执行，这样事务之间就完全不可能产生干扰，也就是说，该级别可以防止脏读、不可重复读以及幻读。
但是这将严重影响程序的性能。通常情况下也不会用到该级别。
查看事务隔离级别
select @@transaction_isolation;
修改事务隔离级别
set global transaction isolation level read committed;
set session transaction isolation level read committed;
设置事务隔离级别
set [session|global] transaction isolation level {read uncommitted|read committed|repeatable read|serializable}
session：针对当前会话
global：针对当前数据库
*/
---------------------------------------------------------------------










show tables;
select database();
show databases; # 查询现有数据库